"""
-------------------------------------------------
  Author:hxy
  Date:2022-09-06 14:47
  Des:sub
-------------------------------------------------
"""

# set PYTHONPATH=D:\pycharm\pywork\django-vue-admin_project\iot_project\backend
import sys
print('sys.path', sys.path)

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
import django
django.setup()

from datetime import datetime
import threading
import paho.mqtt.client as mqtt
from threading import Thread
import logging
from iot.models import Gradation, Cabinet, Point, Unit
from common.tdengine import load_tdengine_pool
from django.db import close_old_connections
import json

_logger = logging.getLogger(__file__)
# host = '192.168.0.244'
host = '39.98.122.153'
TEMP_TYPE = 'T'
publish_topic = 'iot/temp2/trans'

pg_lock = threading.Lock()


def trans(client, value, table):
    key = table
    value_now = round(value, 2)
    payload = {key: value_now}
    client.publish(publish_topic, json.dumps(payload, ensure_ascii=False))
    print(payload)
    points = Point.objects.filter(code=table)
    warm_warning = points.first().cabinet.warm_warning
    warm_early_warning = points.first().cabinet.warm_early_warning
    if warm_warning:
        if value_now > warm_warning:
            client.publish(publish_topic, json.dumps({key+'_warn': 1}, ensure_ascii=False))
            return
    if warm_early_warning:
        if value_now > warm_early_warning:
            client.publish(publish_topic, json.dumps({key+'_warn': 1}, ensure_ascii=False))
            return
    client.publish(publish_topic, json.dumps({key+'_warn': 0}, ensure_ascii=False))


class Sub(Thread):

    def __init__(self, topics, username, password, host, port, client_id):
        super().__init__()
        self.topics = topics
        self.client = mqtt.Client(client_id)
        self.client.username_pw_set(username, password)
        self.client.connect(host=host, port=port)
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.state = True
        self.lt = None

    def on_connect(self, client, userdata, flags, rc):
        rc = str(rc)
        if rc == '0':
            for topic in self.topics:
                self.client.subscribe(topic)
        else:
            _logger.info(f'连接失败: 状态码为{rc}')

    def on_message(self, client, userdata, msg):
        try:
            data_list = eval(msg.payload.decode('utf-8'))
            close_old_connections()
            if data_list:
                point = data_list['sensor']
                point_list = point.split('_')
                data_list['gradation'] = point_list[0]
                if msg.topic == 'iot/temp3':
                    data_list['equipment'] = 'lct3'+data_list['equipment']
                else:
                    data_list['equipment'] = 'lc'+data_list['equipment']
                data_list['type'] = point_list[1]
                data_list['ABC'] = point_list[2]
                data_list['time'] = datetime.now()
                data_list['value'] = float('%.2f' % data_list['value'])
                t = threading.Thread(target=Sub.write_to_td, args=(self, data_list,))
                t.start()
        except Exception as e:
            _logger.error(f'e: {e}')

    def write_to_td(self, data_list):
        point = data_list['sensor']
        equipment = data_list['equipment']
        gradation = data_list['gradation']
        time = data_list['time']
        value = data_list['value']
        type = data_list['type']
        ABC = data_list['ABC']
        table = equipment + '_' + point
        Sub.write_to_pg(equipment, gradation, table, value, type, ABC, time)
        if type == TEMP_TYPE:
            trans(self.client, value, table)
        with load_tdengine_pool().get() as cursor:
            sql = f"INSERT INTO {table} USING iot TAGS ('{equipment}') VALUES ('{time}', '{value}');"
            cursor.execute(sql)

    @staticmethod
    def write_to_pg(equipment, location, table, value, type, ABC, time):
        with pg_lock:
            cabinet = Cabinet.objects.filter(code=equipment)
            if cabinet.count() == 0:
                _logger.info('请配置相关配电站'+equipment)
                return
            gradation = Gradation.objects.filter(code=location)
            if gradation.count() == 0:
                _logger.info('请配置相关电压、温度层级属性')
                return
            unit = Unit.objects.filter(type=type)
            if unit.count() == 0:
                _logger.info('请配置相关单位类型')
                return
            points = Point.objects.filter(code=table)
            if points.count() == 0:
                pass
                # Point.objects.create(gradation=gradation.first(), unit=unit.first(),
                #                      cabinet=cabinet, **{'code': table, 'value': value,
                #                                          'name': ABC+'相'+gradation.first().name,
                #                                          'dept_belong_id': cabinet.dept_belong_id})
            else:
                Point.update(table, **{'value': value, 'update_datetime': time})

    def run(self):
        self.client.loop_forever()


if __name__ == '__main__':
    Sub(topics=['iot/temp2', 'iot/temp3'], username='emqx', password='public', host='39.98.122.153', port=1883, client_id='iot_temp2_sub_39').start()
